// test_integer_sequence.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <tuple>
#include <iostream>
#include <array>
#include <utility>

// Convert array into a tuple
template<typename Array, std::size_t... I>
decltype(auto) a2t_impl(const Array& a, std::index_sequence<I...>)
{
	auto ta = std::make_tuple(a[I]...);

	return ta;
}

template<typename T, std::size_t N, typename Indices = std::make_index_sequence<N>>
decltype(auto) a2t(const std::array<T, N>& a)
{
	auto seq = Indices();
	auto tv = a2t_impl(a, seq);
	return tv;
}

// pretty-print a tuple (from http://stackoverflow.com/a/6245777/273767)

template<class Ch, class Tr, class Tuple, std::size_t... Is>
void print_tuple_impl(std::basic_ostream<Ch, Tr>& os,
	const Tuple & t,
	std::index_sequence<Is...>)
{
	using swallow = int[]; // guaranties left to right order
	swallow{
	 (os << (Is == 0 ? "" : ", ") << std::get<Is>(t),0)...
	};
	using chata = char[];

	auto va = chata{ 'a', 'b' };

	os << va[0] << va[1];
	chata vb{ 'c','d' };
	os << vb[0] << vb[1];

	auto vc = chata{ 'e','f' };

	os << vc[0] << vc[1];
}

template<class Ch, class Tr, class... Args>
decltype(auto) operator<<(std::basic_ostream<Ch, Tr>& os,
	const std::tuple<Args...>& t)
{
	os << "(";
	print_tuple_impl(os, t, std::index_sequence_for<Args...>());
	return os << ")";
}

int main()
{
	auto intmaxvalue = INT_MAX;
	auto longmaxvalue = ULONG_MAX;
	auto doublemaxvalue = DBL_MAX;

	std::cout << intmaxvalue << std::endl;
	std::cout << longmaxvalue << std::endl;
	std::cout << doublemaxvalue << std::endl;
	auto indexclass = std::index_sequence<4>();

	auto vv = std::index_sequence<1, 2, 4>();

	std::array<int, 4> array = { 1,2,3,4 };
	// convert an array into a tuple
	auto tuple = a2t(array);
	static_assert(std::is_same<decltype(tuple), std::tuple<int, int, int, int>>::value, "");

	// print it to cout
	std::cout << tuple << '\n';

	std::cin.get();
}